import ast
import os
from typing import Dict, List, Tuple

class CodeAnalyzer:
    """代码分析器，用于解析和评估代码质量"""
    
    def __init__(self):
        self.analysis_results = {}
    
    def analyze_file(self, file_path: str) -> Dict:
        """分析单个Python文件"""
        if not os.path.exists(file_path) or not file_path.endswith(".py"):
            raise ValueError(f"无效的Python文件: {file_path}")
        
        with open(file_path, "r", encoding="utf-8") as f:
            code = f.read()
        
        try:
            tree = ast.parse(code)
        except SyntaxError as e:
            return {
                "status": "error",
                "file": file_path,
                "error": f"语法错误: {str(e)}",
                "line": e.lineno
            }
        
        # 分析代码结构
        functions = [node.name for node in ast.walk(tree) if isinstance(node, ast.FunctionDef)]
        classes = [node.name for node in ast.walk(tree) if isinstance(node, ast.ClassDef)]
        imports = [
            node.names[0].name for node in ast.walk(tree) 
            if isinstance(node, (ast.Import, ast.ImportFrom))
        ]
        
        # 检查潜在问题
        issues = self._detect_issues(tree, code)
        
        result = {
            "status": "success",
            "file": file_path,
            "functions": functions,
            "classes": classes,
            "imports": imports,
            "line_count": len(code.splitlines()),
            "issues": issues
        }
        
        self.analysis_results[file_path] = result
        return result
    
    def _detect_issues(self, tree: ast.AST, code: str) -> List[Dict]:
        """检测代码中的潜在问题"""
        issues = []
        lines = code.splitlines()
        
        # 检查未使用的变量
        for node in ast.walk(tree):
            if isinstance(node, ast.Assign):
                for target in node.targets:
                    if isinstance(target, ast.Name) and not self._is_variable_used(target.id, tree):
                        issues.append({
                            "type": "unused_variable",
                            "message": f"未使用的变量: {target.id}",
                            "line": node.lineno,
                            "code": lines[node.lineno - 1] if node.lineno <= len(lines) else ""
                        })
        
        # 检查过于复杂的函数
        for node in ast.walk(tree):
            if isinstance(node, ast.FunctionDef):
                complexity = self._calculate_complexity(node)
                if complexity > 10:
                    issues.append({
                        "type": "high_complexity",
                        "message": f"函数复杂度较高 ({complexity}): {node.name}",
                        "line": node.lineno,
                        "code": lines[node.lineno - 1] if node.lineno <= len(lines) else ""
                    })
        
        return issues
    
    def _is_variable_used(self, var_name: str, tree: ast.AST) -> bool:
        """检查变量是否被使用"""
        for node in ast.walk(tree):
            if isinstance(node, ast.Name) and node.id == var_name and isinstance(node.ctx, ast.Load):
                return True
        return False
    
    def _calculate_complexity(self, node: ast.FunctionDef) -> int:
        """计算函数的圈复杂度"""
        complexity = 1  # 基础复杂度
        for n in ast.walk(node):
            if isinstance(n, (ast.If, ast.For, ast.While, ast.Try, ast.ExceptHandler,
                             ast.Break, ast.Continue, ast.Raise)):
                complexity += 1
        return complexity
    
    def analyze_directory(self, dir_path: str) -> Dict:
        """分析目录中的所有Python文件"""
        if not os.path.isdir(dir_path):
            raise ValueError(f"无效的目录: {dir_path}")
        
        results = {}
        for root, _, files in os.walk(dir_path):
            for file in files:
                if file.endswith(".py"):
                    file_path = os.path.join(root, file)
                    results[file_path] = self.analyze_file(file_path)
        
        return results